﻿using System;
using System.Collections.Generic;

namespace Com.OpenCode.DwgConvert.Model
{
    /// <summary>
    /// 几何图形工具类
    /// </summary>
    public static class GeometryUtils
    {
        /// <summary>
        /// 根据圆心 半径
        /// 计算圆上的点
        /// 用来表达圆形图形
        /// </summary>
        /// <param name="centerX">中心点x</param>
        /// <param name="centerY">中心点y</param>
        /// <param name="radio">半径</param>
        /// <returns></returns>
        public static List<DwgPoint> CalcuteCirclePoints(double centerX, double centerY, double radio)
        {
            List<DwgPoint> pointFs = new List<DwgPoint>();
            double step = Math.PI / 180.0;
            for (int i = 0; i < 360; i++)
            {
                double x = centerX + radio * Math.Sin(step * i);
                double y = centerY + radio * Math.Cos(step * i);
                pointFs.Add(new DwgPoint(x, y));
            }
            pointFs.Add(new DwgPoint(pointFs[0].X, pointFs[0].Y));
            return pointFs;
        }

        /// <summary>
        /// 圆弧计算函数
        /// 正弦为0度，逆时针旋转
        /// 圆弧有其特殊性
        /// 如果起始大于终止，则将圆弧分为两部分模拟
        /// </summary>
        /// <param name="centerX">中心点x</param>
        /// <param name="centerY">中心点y</param>
        /// <param name="radio">半径</param>
        /// <param name="start">起始角度</param>
        /// <param name="end">终止角度</param>
        /// <returns></returns>
        public static List<DwgPoint> CalcuteArcPoints(double centerX, double centerY, double radio, double start, double end)
        {
            List<DwgPoint> pointFs = new List<DwgPoint>();
            double step = Math.PI / 180.0;
            if (start > end)
            {
                int count = (int)((2 * Math.PI - start) / step);
                for (int i = 0; i < count; i++)
                {
                    double x = centerX + radio * Math.Sin(start + step * i);
                    double y = centerY + radio * Math.Cos(start + step * i);
                    pointFs.Add(new DwgPoint(x, y));
                }
                count = (int)((end) / step);
                for (int i = 0; i < count; i++)
                {
                    double x = centerX + radio * Math.Sin(step * i);
                    double y = centerY + radio * Math.Cos(step * i);
                    pointFs.Add(new DwgPoint(x, y));
                }
            }
            else
            {
                int count = (int)((end - start) / step);
                for (int i = 0; i < count; i++)
                {
                    double x = centerX + radio * Math.Sin(start + step * i);
                    double y = centerY + radio * Math.Cos(start + step * i);
                    pointFs.Add(new DwgPoint(x, y));
                }
            }
            return pointFs;
        }

        /// <summary>
        /// 计算椭圆的点
        /// </summary>
        /// <param name="centerX"></param>
        /// <param name="centerY"></param>
        /// <param name="majorRadius"></param>
        /// <param name="minorRadius"></param>
        /// <returns></returns>
        public static List<DwgPoint> CalcuteEllipsePoints(double centerX, double centerY, double majorRadius, double minorRadius, double normalX, double normalY)
        {
            List<DwgPoint> pointFs = CalcuteEllipseArcPoints(centerX, centerY, majorRadius, minorRadius, 0, 2 * Math.PI, normalX, normalY);
            pointFs.Add(new DwgPoint(pointFs[0].X, pointFs[0].Y));
            return pointFs;
        }

        /// <summary>
        /// 根据椭圆心 半径
        /// 计算椭圆上的点
        /// 用来表达椭圆形图形
        /// </summary>
        /// <param name="centerX">中心点x</param>
        /// <param name="centerY">中心点y</param>
        /// <param name="radio">半径</param>
        /// <returns></returns>
        public static List<DwgPoint> CalcuteEllipseArcPoints(double centerX, double centerY, double majorRadius, double minorRadius, double start, double end, double normalX, double normalY)
        {
            double rotateAngle = Math.Atan2(normalY, normalX);
            List<DwgPoint> pointFs = new List<DwgPoint>();
            double step = Math.PI / 180.0;
            if (start > end)
            {
                int count = (int)((2 * Math.PI - start) / step);
                for (int i = 0; i < count; i++)
                {
                    pointFs.Add(CalcuteGetEllipseArcPoint(centerX, centerY, majorRadius, minorRadius, start + step * i, rotateAngle));
                }
                count = (int)((end) / step);
                for (int i = 0; i < count; i++)
                {
                    pointFs.Add(CalcuteGetEllipseArcPoint(centerX, centerY, majorRadius, minorRadius, step * i, rotateAngle));
                }
            }
            else
            {
                int count = (int)((end - start) / step);
                for (int i = 0; i < count; i++)
                {
                    pointFs.Add(CalcuteGetEllipseArcPoint(centerX, centerY, majorRadius, minorRadius, start + step * i, rotateAngle));
                }
            }
            return pointFs;
        }

        /// <summary>
        /// 根据长短半轴计算椭圆上的一个点
        /// </summary>
        /// <param name="majorRadius"></param>
        /// <param name="minorRadius"></param>
        /// <param name="angle"></param>
        /// <returns></returns>
        public static DwgPoint CalcuteGetEllipseArcPoint(double centerX, double centerY, double majorRadius, double minorRadius, double angle, double rotateAngle)
        {
            DwgPoint dwgPoint = new DwgPoint();
            double a = majorRadius;
            double b = minorRadius;
            double yc = Math.Sin(angle);
            double xc = Math.Cos(angle);
            double radio = (a * b) / Math.Sqrt(Math.Pow(yc * a, 2.0) + Math.Pow(xc * b, 2.0));
            double ax = radio * xc;
            double ay = radio * yc;
            double rotatex = ax * Math.Cos(rotateAngle) - ay * Math.Sin(rotateAngle);
            double rotatey = ax * Math.Sin(rotateAngle) + ay * Math.Cos(rotateAngle);
            dwgPoint.X = centerX + rotatex;
            dwgPoint.Y = centerY + rotatey;
            return dwgPoint;
        }

        /// <summary>
        /// 计算贝斯尔取消
        /// </summary>
        /// <returns></returns>
        public static List<DwgPoint> CalcuteSplinePoints()
        {
            return null;
        }
    }
}
